﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using AdvUtils;
using GeoUtils;

namespace BuildGeoEntityFromMIF
{
    class GeoEntityBuilder
    {
        GeoEntityStorage geoItemStorage = new GeoEntityStorage();
        RewriteAddress rewriteAddress = new RewriteAddress();
        Dictionary<string, List<string>> geoName2TagList = new Dictionary<string, List<string>>();

        int maxId = 0;
        SortedDictionary<string, int> sdict = new SortedDictionary<string, int>(StringComparer.Ordinal);

        public GeoEntityBuilder()
        {
            rewriteAddress.Initialize();


        }

        public void Build(string strEncodedGeoEntityFileName)
        {
            StreamWriter swGeoNameLexicalDict = new StreamWriter(strEncodedGeoEntityFileName + ".txt");
            //Save geo entity name and its tags into file
            foreach (KeyValuePair<string, List<string>> pair in geoName2TagList)
            {
                string strTagList = "";
                foreach (string item in pair.Value)
                {
                    strTagList = strTagList + "|" + item;
                }
                strTagList = strTagList.Substring(1);

                swGeoNameLexicalDict.WriteLine("{0}\t{1}", pair.Key, strTagList);
            }
            swGeoNameLexicalDict.Close();


            //Build geo entities index into double array trie-tree
            DoubleArrayTrieBuilder daBuilder = new DoubleArrayTrieBuilder(4);
            daBuilder.build(sdict);
            daBuilder.save(strEncodedGeoEntityFileName + ".dart");

            Console.WriteLine("Build Geo Entities Data...");
            //Build geo entities data
            geoItemStorage.SaveIntoFile(strEncodedGeoEntityFileName + ".dat");

        }

        public void AddNewGeoEntity(GeoEntity geoEntity, string strTag)
        {
            if (maxId % 10000 == 0)
            {
                Console.WriteLine("{0}\t{1}\t{2}", geoEntity.Name, geoEntity.LatLong.Latitude, geoEntity.LatLong.Longitude);
            }

            //Add geo entity's name and tags pair
            if (geoName2TagList.ContainsKey(geoEntity.Name) == false)
            {
                geoName2TagList.Add(geoEntity.Name, new List<string>());
            }
            if (geoName2TagList[geoEntity.Name].Contains(strTag) == false)
            {
                geoName2TagList[geoEntity.Name].Add(strTag);
            }

            //Build geo entity index for double array trie-tree
            if (sdict.ContainsKey(geoEntity.Name) == true)
            {
                int idx = sdict[geoEntity.Name];
                geoItemStorage.AddNewItemAt(idx, geoEntity);
            }
            else
            {
                sdict.Add(geoEntity.Name, maxId);
                geoItemStorage.AddNewItem(geoEntity);
                maxId++;
            }


            List<string> rewriteList = null;

            //Get rewritten result according geo-entity's type
            if (strTag.StartsWith("DICT_LOC_ADMIN") == true)
            {
                rewriteList = rewriteAddress.RewriteAdminName(geoEntity.Name);
            }
            else if (strTag.StartsWith("DICT_LOC_ROD") == true)
            {
                rewriteList = rewriteAddress.RewriteRoadName(geoEntity.Name);
            }
            else
            {
                rewriteList = new List<string>();
            }

            //Add geo-entity rewritten result into indexed data
            foreach (string item in rewriteList)
            {
                if (item.Length < 2)
                {
                    continue;
                }


                //Add geo entity's name and tags pair
                if (geoName2TagList.ContainsKey(item) == false)
                {
                    geoName2TagList.Add(item, new List<string>());
                }
                if (geoName2TagList[item].Contains(strTag) == false)
                {
                    geoName2TagList[item].Add(strTag);
                }

                //Build geo entity index for double array trie-tree
                GeoEntity ge = new GeoEntity(item, strTag, true, geoEntity.AdminCodeList, geoEntity.AdminPreCode,
                    geoEntity.iLevel, geoEntity.LatLong, geoEntity.BoundingPolygon);
                if (sdict.ContainsKey(item) == true)
                {
                    int idx = sdict[item];
                    geoItemStorage.AddNewItemAt(idx, ge);
                }
                else
                {
                    sdict.Add(item, maxId);
                    geoItemStorage.AddNewItem(ge);
                    maxId++;
                }
            }

        }

    }
}
